home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / x2ftp / msdos / mxlibs / sbvox / sbvox.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-10-28  |  17.7 KB  |  415 lines

  1. {
  2.  SBVOX    Ethan Brodsky     ericbrodsky@psl.wisc.edu    Last Updade: 10/18/94
  3.  This code is released into the public domain.  You can do anything you want
  4.  with it, but please give me credit.  If you make improvements or discover a
  5.  bug, please send it to me.  This code incorporates nice features from many
  6.  SBVoice libraries(Also known as CTVoice and VoxTool)  with some of my own
  7.  ideas.  The basic procedure for using this library is shown in the VOCPLAY
  8.  and RECPLAY example programs.  This version supercedes all other SBVox and
  9.  SBVoice libraries written by me.  It is improved and supports VOC files that
  10.  are larger than 64k and allows you to link the CT-VOICE driver into your
  11.  executable.  If you want to do this, make sure that CT-VOICE.DRV is in the
  12.  current directory and that BINOBJ (Comes with TP) is in your search path,
  13.  and run SETUP.BAT.  After you have CT-VOICE.OBJ, $DEFINE LinkDriver in this
  14.  unit and modify your program accordingly.  This may not be a good idea if
  15.  you want your program to support different versions of the Sound Blaster
  16.  sound card (The CT-VOICE driver is not compatible between sound cards)
  17.  Good luck, and please tell me how you have used this library,
  18.      Ethan Brodsky
  19. }
  20. unit SBVox;
  21. {-} interface {--------------------------------------------------------------}
  22.         const
  23.             SpeakerOff = 0; SpeakerOn  = 1;
  24.  
  25.             SoundCompleted = 0;
  26.  
  27.             LoadDrvSuccess    =  0;
  28.             LoadDrvIOerror    =  1;
  29.             LoadDrvNoMemory   =  2;
  30.             LoadDrvBadDriver  =  3;
  31.  
  32.             SBInitSuccess               = 0;
  33.             SBInitSoundCardFailure      = 1;
  34.             SBInitIOFailure             = 2;
  35.             SBInitDMAorInterruptFailure = 3;
  36.  
  37.             BreakLoopAtEnd = 0;
  38.             BreakLoopNow   = 1;
  39. {$IFNDEF LinkDriver}
  40.         function LoadDriver(DriverPath: string): integer;
  41.           {Loads CT-VOICE.DRV into memory from the disk.                     }
  42.         procedure UnloadDriver;
  43.           {Unloads the driver from memory.  Call this after you are done with}
  44.           {the Sound Blaster.   If the driver is linked into the executable, }
  45.           {this is not needed.   Just call ShutDownDriver to shut down the SB}
  46. {$ENDIF}
  47.         var
  48.             StatusWord : word;
  49.         type
  50.             TSound     = array[1..65535] of byte;
  51.               {Only works to access first 64k of the sound}
  52.             PSound     = ^TSound;
  53.             PVOCHeader = ^TVOCHeader;
  54.             TVOCHeader = array[1..26] of char;
  55.  
  56.         function GetDriverVersion: word;
  57.           {Get the version number of the CT-VOICE.DRV                        }
  58.           {Returns the Version number                                        }
  59.           {Hi(GetDriverVersion) is the major revision number                 }
  60.           {Lo(GetDriverVersion) is the minor revision number                 }
  61.         procedure SetInterrupt(NewInterruptNum: word);
  62.           {Override the interrupt number stored in the CT-VOICE driver       }
  63.           {You must call this BEFORE InitSB                                  }
  64.         procedure SetBaseIOAddress(NewAddress: word);
  65.           {Override the base IO address stored inside the CT-VOICE driver    }
  66.           {You must call this BEFORE InitSB                                  }
  67.         function InitSB: integer;
  68.           {Initialize the SoundBlaster.  Call this right after load driver   }
  69.           {unless you have to change the Base IO address or interrupt number.}
  70.           {In that case, call SetInterrupt and SetBaseIOAddress              }
  71.           {Returns:  0 - no problem                                          }
  72.           {          1 - sound card failiure                                 }
  73.           {          2 - I/O failiure                                        }
  74.           {          3 - DMA interrupt failiure                              }
  75.         procedure InitStatusWord;
  76.           {Sets the location of the status word.  This is the third thing you}
  77.           {should do, after loading the driver and initializing it. The      }
  78.           {StatusWord will contain $FFFF if input/output is in output, and 0 }
  79.           {when it's done.  It will also hold the values of the markers in   }
  80.           {voice files if any are encounterred, allowing you to synchronize  }
  81.           {sound output with your program.                                   }
  82.         function GetSoundBuffer(var Sound: PSound; BufferLength: LongInt): boolean;
  83.           {THIS FUNCTION CAN ALLOCATE MORE THAN 64K!!!!!!!!!!!!!!!!!!!!!!!!!!}
  84.           {Allocates a buffer for a sound.  Returns true if successful, false}
  85.           {if memory  cannot be  allocated.    I haven't tested it in a large}
  86.           {program yet.   It will surely work for buffers under 64k.   If you}
  87.           {have a better way,  please contact me.   If you find a bug, please}
  88.           {contact me so I can fix it                                        }
  89.         procedure FreeSoundBuffer(Sound: PSound; BufferLength: LongInt);
  90.           {Deallocates the memory allocated by GetSoundBuffer                }
  91.         function LoadVOCFile(FileName: string; var Header: PVOCHeader; var Sound: PSound): LongInt;
  92.           {Returns the size of the VOC buffer                                }
  93.         procedure SetSpeakerState(State: word);
  94.           {Set the speaker on/off.  Off is state 0, and On is anything else. }
  95.         procedure TurnSpeakerOn;
  96.           {Turns on the speaker                                              }
  97.         procedure TurnSpeakerOff;
  98.           {Turns off the speaker                                             }
  99.         procedure PlaySound(Sound: PSound);
  100.           {Outputs digitized sound.                                          }
  101.           {Sound:       Pointer to the sound buffer                          }
  102.           {To find out when the output is completed, check if StatusWord = 0 }
  103.         procedure StopSound;
  104.           {Stops the IO in progress                                          }
  105.         procedure PauseSound;
  106.           {Pauses the input or output in progress.  Resume with ContinueSound}
  107.         procedure ContinueSound;
  108.           {Continues input or output paused with PauseSouund                 }
  109.         procedure BreakLoop(BreakType: word);
  110.           {Breaks out of the current output loop.                            }
  111.           {BreakTypes: 0 - continue round, stop when done                    }
  112.           {            1 - stop immediately                                  }
  113.         procedure RecordSound(Sound: PSound; SoundLength: LongInt; Rate: word);
  114.           {Input digitized sound.                                            }
  115.           {Sound:       Pointer to the sound buffer.                         }
  116.           {SoundLength: Length of the input buffer.                          }
  117.           {Rate:        Sampling frequency                                   }
  118.           {To find out when the sound buffer is full, check if StatusWord = 0}
  119.         procedure SetUserFunction(UserFunction: pointer);
  120.           {Sets up a user function that the SB calls when it encounters a new}
  121.           {data block.   It must perform a FAR return,  preserving DS, DI, SI}
  122.           {and  the  flags  register.    Clear the Carry flag if you want the}
  123.           {driver to process the block,  or set it if your routine will.  The}
  124.           {carry flag must be cleared if the block type is 0,  then it is the}
  125.           {terminate block.                                                  }
  126.         procedure ShutDownDriver;
  127.           {Notifies the Sound Blaster that the driver is being installed.  No}
  128.           {need to call this directly unless you want to shut down the  Sound}
  129.           {Blaster without removing the driver from memory,  such as when the}
  130.           {driver is linked into the exectable.                              }
  131. {-} implementation {---------------------------------------------------------}
  132. {$IFDEF LinkDriver}
  133.         uses VOXDrv;  {The driver must be aligned on a segment boundary}
  134. {$ENDIF}
  135.         var
  136.             SBDriver : pointer;
  137.             DriverSize : word;
  138. {$IFNDEF LinkDriver}
  139.         function LoadDriver(DriverPath: string): integer;
  140.             type
  141.                 PTitle = ^TTitle;
  142.                 TTitle = array[1..8] of char;
  143.             var
  144.                 f     : file;
  145.                 i     : integer;
  146.                 Title : TTitle;
  147.             begin
  148.                 SBDriver := nil;
  149.                 LoadDriver := LoadDrvSuccess;
  150.                 Assign(f, DriverPath);
  151.                 {$I-} Reset(f,1); {$I+}
  152.                 DriverSize := FileSize(f);
  153.                 if IOResult <> 0
  154.                     then
  155.                         begin
  156.                             LoadDriver := LoadDrvIOerror;
  157.                             Exit;
  158.                         end;
  159.                 if MaxAvail < FileSize(f)
  160.                     then
  161.                         begin
  162.                             LoadDriver := LoadDrvNoMemory;
  163.                             Exit;
  164.                         end;
  165.                 StatusWord := 0;
  166.                 GetMem(SBDriver, DriverSize);
  167.                 BlockRead(f, SBDriver^, DriverSize);
  168.                 Close(f);
  169.  
  170.                 Title := PTitle(Ptr(Seg(SBDriver^), Ofs(SBDriver^)+3))^;
  171.  
  172.                 if Title <> 'CT-VOICE'
  173.                    then
  174.                        begin
  175.                            LoadDriver := LoadDrvBadDriver;
  176.                            FreeMem(SBDriver, DriverSize);
  177.                            Exit;
  178.                        end;
  179.            end;
  180.         procedure UnloadDriver;
  181.             begin
  182.                 ShutDownDriver;
  183.                 FreeMem(SBDriver, DriverSize);
  184.                 SBDriver := nil;
  185.             end;
  186. {$ENDIF}
  187.         function GetDriverVersion: word; assembler;
  188.             asm
  189.                 PUSH  BP
  190.                 MOV   BX, 0
  191.                 CALL  SBDriver
  192.                 POP   BP
  193.             end;
  194.         procedure SetBaseIOAddress(NewAddress: word); assembler;
  195.             asm
  196.                 PUSH  BP
  197.                 MOV   AX, NewAddress
  198.                 MOV   BX, 1
  199.                 CALL  SBDriver
  200.                 POP   BP
  201.             end;
  202.         procedure SetInterrupt(NewInterruptNum: word); assembler;
  203.             asm
  204.                 PUSH  BP
  205.                 MOV   AX, NewInterruptNum
  206.                 MOV   BX, 2
  207.                 CALL  SBDriver
  208.                 POP   BP
  209.             end;
  210.         function InitSB: integer; assembler;
  211.             asm
  212.                 PUSH  BP
  213.                 MOV   BX, 3
  214.                 CALL  SBDriver
  215.                 POP   BP
  216.             end;
  217.         procedure SetSpeakerState(State: word); assembler;
  218.             asm
  219.                 PUSH  BP
  220.                 MOV   AX, State
  221.                 MOV   BX, 4
  222.                 CALL  SBDriver
  223.                 POP   BP
  224.             end;
  225.         procedure TurnSpeakerOn;
  226.             begin
  227.                 SetSpeakerState(SpeakerOn);
  228.             end;
  229.         procedure TurnSpeakerOff;
  230.             begin
  231.                 SetSpeakerState(SpeakerOff);
  232.             end;
  233.         procedure InitStatusWord;
  234.             var
  235.                 StatusWordPtr: ^Word;
  236.             begin
  237.                 StatusWordPtr := @StatusWord;
  238.                     asm
  239.                         MOV  BX, 5
  240.                         LES  DI, StatusWordPtr
  241.                         CALL SBDriver
  242.                     end;
  243.             end;
  244.         function GetSoundBuffer(var Sound: PSound; BufferLength: LongInt): boolean;
  245.             var
  246.                 Dummy: pointer;
  247.             begin
  248.                 if MaxAvail < BufferLength
  249.                     then
  250.                         begin
  251.                             GetSoundBuffer := false;
  252.                             Exit;
  253.                         end;
  254.                 GetSoundBuffer := true;
  255.                 if BufferLength < $FFFF
  256.                     then
  257.                         GetMem(Sound, BufferLength)
  258.                     else
  259.                         begin
  260.                             GetMem(Sound, $FFFF);
  261.                             BufferLength := BufferLength - $FFFF;
  262.                             while BufferLength > $FFFF do
  263.                                 begin
  264.                                     GetMem(Dummy, $FFFF);
  265.                                     BufferLength := BufferLength - $FFFF;
  266.                                 end;
  267.                             GetMem(Dummy, BufferLength);
  268.                         end;
  269.             end;
  270.         procedure FreeSoundBuffer(Sound: PSound; BufferLength: LongInt);
  271.             var
  272.                 Dummy: pointer;
  273.                 LeftToFree: LongInt;
  274.             begin
  275.                 if BufferLength < $FFFF
  276.                     then
  277.                         FreeMem(Sound, BufferLength)
  278.                     else
  279.                         begin
  280.                             Dummy := Sound;
  281.                             LeftToFree := BufferLength;
  282.                             FreeMem(Sound, $FFFF);
  283.                             LeftToFree := LeftToFree - $FFFF;
  284.                             Dummy := Ptr(Seg(Dummy^) + $1000, Ofs(Dummy^));
  285.                             while LeftToFree > $FFFF do
  286.                                 begin
  287.                                     FreeMem(Dummy, $FFFF);
  288.                                     LeftToFree := LeftToFree - $FFFF;
  289.                                     Dummy := Ptr(Seg(Dummy^) + $1000, Ofs(Dummy^));
  290.                                 end;
  291.                             FreeMem(Dummy, LeftToFree);
  292.                         end;
  293.             end;
  294.         function LoadVOCFile(FileName: string; var Header: PVOCHeader; var Sound: PSound): LongInt;
  295.            var
  296.                 f: file;
  297.                 Dummy: Pointer;
  298.                 LeftToRead: LongInt;
  299.             begin
  300.                 Assign(f, FileName);
  301.                 Reset(f, 1);
  302.                 LoadVOCFile := (FileSize(f) - SizeOf(Header^));
  303.                 New(Header);
  304.                 BlockRead(f, Header^, SizeOf(Header^));
  305.  
  306.                 if GetSoundBuffer(Sound, FileSize(f) - SizeOf(Header^)) <> true
  307.                     then
  308.                         begin
  309.                             LoadVOCfile := 0; {Failed to allocate memory}
  310.                             Exit;
  311.                         end;
  312.                 LeftToRead := FileSize(f) - SizeOf(Header^);
  313.                 Dummy := Sound;
  314.                 if LeftToRead < $FFF0
  315.                     then
  316.                         BlockRead(f, Sound^, LeftToRead)
  317.                     else
  318.                         begin
  319.                             BlockRead(f, Sound^, $FFF0);
  320.                             LeftToRead := LeftToRead - $FFF0;
  321.                             Dummy := Ptr(Seg(Dummy^) + $1000, Ofs(Dummy^));
  322.                             while LeftToRead > $FFF0 do
  323.                                 begin
  324.                                     BlockRead(f, Dummy^, $FFF0);
  325.                                     LeftToRead := LeftToRead - $FFF0;
  326.                                     Dummy := Ptr(Seg(Dummy^) + $1000, Ofs(Dummy^));
  327.                                 end;
  328.                             BlockRead(f, Dummy^, LeftToRead);
  329.                         end;
  330.                 Close(f);
  331.             end;
  332.         procedure PlaySound(Sound: PSound);
  333.             begin
  334.                     asm
  335.                         MOV  BX, 6
  336.                         LES  DI, Sound
  337.                         CALL SBDriver
  338.                     end;
  339.             end;
  340.         procedure StopSound; assembler;
  341.             asm
  342.                 PUSH  BP
  343.                 MOV   BX, 8
  344.                 CALL  SBDriver
  345.                 POP   BP
  346.             end;
  347.         procedure PauseSound; assembler;
  348.             asm
  349.                 PUSH  BP
  350.                 MOV   BX, 10
  351.                 CALL  SBDriver
  352.                 POP   BP
  353.             end;
  354.         procedure ContinueSound; assembler;
  355.             asm
  356.                 PUSH  BP
  357.                 MOV   BX, 11
  358.                 CALL  SBDriver
  359.                 POP   BP
  360.             end;
  361.         procedure BreakLoop(BreakType: word); assembler;
  362.             asm
  363.                 PUSH  BP
  364.                 MOV   AX, BreakType
  365.                 MOV   BX, 12
  366.                 CALL  SBDriver
  367.                 POP   BP
  368.             end;
  369.         procedure RecordSound(Sound: PSound; SoundLength: LongInt; Rate: word);
  370.             type
  371.                 LongRec =
  372.                     record
  373.                         Lo, Hi: Word;
  374.                     end;
  375.             var
  376.                 HiLength, LoLength : word;
  377.             begin
  378.                 LoLength := LongRec(SoundLength).Lo;
  379.                 HiLength := LongRec(SoundLength).Hi;
  380.                     asm
  381.                         MOV  AX, Rate
  382.                         MOV  BX, 7
  383.                         MOV  CX, LoLength
  384.                         MOV  DX, HiLength
  385.                         LES  DI, Sound
  386.                         CALL SBDriver
  387.                     end;
  388.             end;
  389.         procedure SetUserFunction(UserFunction: pointer);
  390.             var
  391.                 SegAddress, OfsAddress: word;
  392.             begin
  393.                 SegAddress := Seg(UserFunction^);
  394.                 OfsAddress := Ofs(UserFunction^);
  395.                     asm
  396.                         MOV   AX, OfsAddress
  397.                         MOV   BX, 13
  398.                         MOV   DX, SegAddress
  399.                         CALL  SBDriver
  400.                     end;
  401.             end;
  402.         procedure ShutDownDriver; assembler;
  403.             asm
  404.                 PUSH  BP
  405.                 MOV   BX, 9
  406.                 CALL  SBDriver
  407.                 POP   BP
  408.             end;
  409.     begin
  410. {$IFDEF LinkDriver}
  411.         SBDriver := @CTVoice;
  412. {$ELSE}
  413.         SBDriver := nil;
  414. {$ENDIF}
  415.     end.